home *** CD-ROM | disk | FTP | other *** search
- ;************* EQUATES FOR THE ASSEMBLER ***************************************
-
- KYBD_DATA EQU 60H ;KEYBOARD DATA PORT
- KYBD_CTL EQU 61H ;KEYBOARD CONTROL PORT
- KYBD_SEOI EQU 61H ;SPECIFIC END OF INTERRUPT CODE FOR
- ; INT 09H KEYBOARD HARDWARE SERVICE
- PIC_CTL EQU 20H ;PIC CONTROL PORT
-
- ;************* AN EXTRA SEGMENT ************************************************
-
- SCREEN SEGMENT AT 0B000H ;EXTRA SEGMENT SO WE CAN WRITE
- SCREEN ENDS ; TO THE SCREEN.
-
- ;************* THE CODE SEGMENT ************************************************
-
- CODE_SEG SEGMENT
- ASSUME CS:CODE_SEG
- ORG 100H
-
- FIRST: JMP LOAD_CLOCK ;1ST TIME THRU, INITIALIZE.
-
- ;------------- DATA DEFINITIONS ------------------------------------------------
-
- MESSAGE DB ' ' ;THIS IS THE CLOCK DISPLAY.
- MSG_HOURS DW ?
- DB ':'
- MSG_MINUTES DW ?
- DB ':'
- MSG_SECONDS DW ?
- DB ' '
- AMPM DB ' '
- DB 'M '
-
- SCREEN_ATTR DB 1EH ;BRIGHT YELLOW ON CYAN
-
- STATUS_PORT DW 03BAH ;VIDEO CONTROLLER STATUS PORT
-
- CURR_HOUR DB ? ;STORAGE FOR THE CURRENT TIME.
- CURR_MIN DB ?
- CURR_SEC DB ?
-
- PREV_SEC DB ?
-
- ON_OFF_FLAG DB 1 ;PROGRAM ON/OFF TOGGLE FLAG
- KEY_WATCH DB 0 ;ALT KEY DEPRESSED FLAG
- COUNTER DB 0
- WORKING DB 0 ;PGM IN PROGRESS FLAG.
-
- FIRST_POSITION DW ? ;POS OF 1ST CHAR ON SCREEN.
- SCREEN_SEG_OFFSET DW 0 ;0 FOR MONO, 8000H FOR COLOR.
- OLD_TIMER_INT DD ? ;LOC OF OLD TIMER INTERRUPT ROUTINE.
- OLD_INT09H DD ? ;LOC OF OLD KYBD I/O INTERRUPT
-
- ;-------------------------------------------------------------------------------
-
- CLOCK PROC FAR ;THE TIMER INTERRUPT WILL NOW
- ASSUME CS:CODE_SEG ; COME HERE.
-
- STI ;ALLOW HARDWARE INTERRUPTS.
- CMP WORKING,1 ;IS PROGRAM ALREADY RUNNING?
- JNE CHK_COUNTER ; NO, CONTINUE.
- JMP FIN ; YES, EXIT.
-
- CHK_COUNTER: INC COUNTER ;INCREMENT OUR COUNTER
- CMP COUNTER,3 ;ARE WE READY TO RUN?
- JNB CHK_TOGGLE ;YES, CONTINUE
- JMP FIN ;NO, EXIT
-
- CHK_TOGGLE: CMP ON_OFF_FLAG,1 ;SHOULD WE DO THE CLOCK?
- JE SAVE_OLD ;YES, CONTINUE
- JMP FIN ;NO, EXIT
-
- SAVE_OLD: MOV WORKING,1
- MOV COUNTER,0
- PUSH AX ;SAVE USED REGISTER
- PUSH BX ;SAVE USED REGISTERS.
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH ES
-
- GET_TIME: MOV AH,-2 ;GET TICKS OF BIOS TIMER.
- INT 1AH ;CX=HIGH COUNT, DX=LOW COUNT.
- MOV CURR_HOUR,CH
- MOV CURR_MIN,CL
- MOV CURR_SEC,DH
-
- CHECK_PREV: CMP DH,PREV_SEC ;TIME TO UPDATE DISPLAY?
- JNE UPDATE_PREV ; YES, RUN WITH IT
- JMP RESET_OLD ; NO, EXIT
-
- UPDATE_PREV: MOV PREV_SEC,DH ;UPDATE PREVIOUS SECOND FIELD
-
- CHECK_AMPM: CMP CURR_HOUR,12 ;ARE WE IN AM OR PM TIME?
- JB AM_HOUR ; IF HOURS<12, IT'S AM
- JZ NOON ; IF HOURS=12 IT'S NOON, DISPLAY A 12
- SUB CURR_HOUR,12 ; OTHERWISE, IT'S PM.
- NOON: MOV AMPM,'P' ;SET PM FLAG.
- JMP CREATE_MSG
-
- AM_HOUR: MOV AMPM,'A' ;SET AM FLAG.
- CMP CURR_HOUR,0 ;IS IT MIDNIGHT?
- JNE CREATE_MSG ; NO, CONTINUE.
- MOV CURR_HOUR,12 ; YES, DISPLAY A 12.
-
- CREATE_MSG: MOV AL,CURR_HOUR ;CONVERT HOURS TO ASCII.
- CALL BIN_TO_ASCII
- MOV MSG_HOURS,AX ;MOVE HOURS TO MSG AREA.
- MOV AL,CURR_MIN ;CONVERT MINUTES TO ASCII.
- CALL BIN_TO_ASCII
- MOV MSG_MINUTES,AX ;MOVE MINUTES TO MSG AREA.
- MOV AL,CURR_SEC ;CONVERT SECONDS TO ASCII.
- CALL BIN_TO_ASCII
- MOV MSG_SECONDS,AX ;MOVE SECONDS TO MSG AREA.
-
- SET_ES: ASSUME ES:SCREEN ;SET ES TO POINT TO THE SCREEN.
- MOV DX,SCREEN
- MOV ES,DX
-
- WRITE_MSG: MOV CX,13 ;WRITE 8 CHARACTERS.
- MOV SI,OFFSET MESSAGE ;ADDRESS OF STRING TO MOVE.
- MOV DI,SCREEN_SEG_OFFSET
- ADD DI,FIRST_POSITION ;DESTINATION ADDRESS FOR THE MOVE.
- MOV DX,STATUS_PORT ;VIDEO STATUS PORT NUMBER
- CLI ;NO HARDWARE INTERRUPTS UNTIL DONE
-
- WAIT_LOW_1: IN AL,DX ;WAIT FOR SCAN STATUS TO GO LOW.
- TEST AL,1
- JNZ WAIT_LOW_1
- WAIT_HIGH_1: IN AL,DX ;AFTER SCAN STATUS GOES LOW, IT MUST GO
- TEST AL,1 ; HIGH BEFORE WE CAN WRITE DIRECTLY TO
- JZ WAIT_HIGH_1 ; THE VIDEO BUFFER WITHOUT CAUSING SNOW.
-
- WRITE_CHAR: MOVS ES:BYTE PTR[DI],CS:[SI]
-
- WAIT_LOW_2: IN AL,DX ;WAIT FOR SCAN STATUS TO GO LOW.
- TEST AL,1
- JNZ WAIT_LOW_2
- WAIT_HIGH_2: IN AL,DX ;AFTER SCAN STATUS GOES LOW, IT MUST GO
- TEST AL,1 ; HIGH BEFORE WE CAN WRITE DIRECTLY TO
- JZ WAIT_HIGH_2 ; THE VIDEO BUFFER WITHOUT CAUSING SNOW.
-
- WRITE_ATTR: MOV AL,SCREEN_ATTR ;SCREEN ATTRIBUTE CHAR. TO USE
- MOV ES:[DI],AL
- INC DI
- LOOP WAIT_LOW_1
- STI ;OK TO ALLOW INTERRUPTS NOW.
-
- RESET_OLD: POP ES ;POP THE PUSHED REGISTERS.
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP AX ;POP THE PUSHED REGISTERS.
- MOV WORKING,0 ;RESET PGM IN PROGRESS FLAG.
-
- FIN: JMP OLD_TIMER_INT ;LET OLD ISR ISSUE THE IRET
-
- CLOCK ENDP
-
- ;*******************************************************************************
-
- BIN_TO_ASCII PROC NEAR
-
- ; THIS PROCEDURE CONVERTS A BINARY NUMBER IN AL INTO
- ; 2 ASCII CHARACTERS IN AX. THE LEAST SIGNIFIGANT BYTE IS
- ; RETURNED IN AH, THE MOST SIGNIFICANT BYTE IN AL.
-
- PUSH CX ;SAVE USED REGISTER FOR POLITENESS.
- XOR AH,AH ;ZERO OUT AH.
- MOV CL,10 ;DIVISOR FOR HEX TO DEC CONVERT.
- DIV CL ;CONVERT AL TO DECIMAL QUOTIENT (TENS)
- ; REMAINDER GOES IN AH (ONES).
- ADD AL,30H ;CONVERT AL TO ASCII.
- ADD AH,30H ;CONVERT AH TO ASCII.
- POP CX ;RESTORE PUSHED REGISTER.
-
- RET ;RETURN TO CALLER.
- BIN_TO_ASCII ENDP
-
- ;*******************************************************************************
-
- int09h proc far
- ;
- ; This procedure is used to service the keyboard hardware interrupt for
- ; the scrclock.com program. It will check to see if the on/off trigger
- ; key has been pressed. If it has, the on_off flag will be toggled.
- ;
- assume ds:nothing
- sti
- push ax ;save the used register
-
- get_scan: in al,kybd_data ;get a byte from kybd data port
- cmp al,38h ;alt key "make"?
- jne alt_break ;no, check for "break"
- mov key_watch,1 ;set alt key flag
- jmp int_service ;and jump to the original isr
-
- alt_break: cmp al,0b8h ;alt key "break"?
- jne chk_watch ;no, go check alt key flag
- mov key_watch,0 ;clear alt key flag
- jmp int_service ;and jump to original isr
-
- chk_watch: cmp key_watch,1 ;alt key flag set?
- jne int_service ;no, jump to original isr
-
- d_make: cmp al,20h ;d key "make"?
- jne d_break ;no, check for d key "break"
- xor on_off_flag,01h ;toggle the clock
- jmp reset_kybd ;go reset the keyboard
-
- d_break: cmp al,0a0h ;d key "break"?
- je reset_kybd ;yes, reset the keyboard
-
- int_service: pop ax ;pop the pushed register
- jmp old_int09h ;let original routine issue the iret
-
- reset_kybd: in al,kybd_ctl ;reset keyboard status
- push ax ;then iret back to caller
- or al,80h
- out kybd_ctl,al
- pop ax
- out kybd_ctl,al
- cli ;disable interrupts
- mov al,kybd_seoi ;send a "specific end of interrupt"
- out pic_ctl,al ;to the pic controller chip
- sti ;re-enable interrupts
- pop ax
- iret
-
- int09h endp
-
-
- ;*******************************************************************************
-
- LOAD_CLOCK PROC NEAR ;THIS PROC INITIALIZES EVERYTHING.
-
- SCREEN_SETUP: MOV AH,15 ;ASK FOR SERVICE 15 OF INT 10H.
- INT 10H ;TELLS HOW DISPLAY IS SET UP.
- SUB AH,13 ;MOVE TO 13 PLACES BEFORE EDGE.
- SHL AH,1 ;MULT. BY 2 (CHAR & ATTR BYTES).
- MOV BYTE PTR FIRST_POSITION,AH ;SET SCREEN CURSOR POSITION.
- TEST AL,4 ;IS IT A MONO SCREEN?
- JNZ GET_OLD_INT ; YES - ADJUSTMENT NOT REQUIRED.
- MOV SCREEN_SEG_OFFSET,8000H ; NO - SET UP FOR COLOR.
- MOV STATUS_PORT,03DAH
-
- GET_OLD_INT: MOV AH,35H ;GET VECTOR FUNCTION
- MOV AL,1CH ;TIMER INTERRUPT NUMBER
- INT 21H ;CALL DOS
- MOV WORD PTR OLD_TIMER_INT,BX ;STORE OFFSET
- MOV WORD PTR OLD_TIMER_INT[2],ES ;STORE SEGMENT
-
- SET_NEW_INT: MOV DX,OFFSET CLOCK ;DS:DX IS NEW INTERRUPT ADDRESS.
- MOV AL,1CH ;1CH IS THE INTERRUPT TO CHANGE.
- MOV AH,25H ;DOS FUNCTION 25H TO RESET VECTOR.
- INT 21H ;CALL DOS.
-
- GET_OLD_KYBD: MOV AH,35H ;GET VECTOR FUNCTION
- MOV AL,09H ;KEYBOARD HARDWARE INTERRUPT
- INT 21H ;CALL DOS
- MOV WORD PTR OLD_INT09H,BX ;SAVE OFFSET
- MOV WORD PTR OLD_INT09H[2],ES ;SAVE SEGMENT
-
- SET_NEW_KYBD: MOV DX,OFFSET INT09H ;OFFSET OF NEW KYBD I/O INTERR.
- MOV AH,25H ;DS ALREADY SET. AH=SET VECTOR.
- MOV AL,09H ;INT. NUMBER TO SET - KYBD I/O
- INT 21H ;CALL DOS
-
- LOAD_MSG: MOV DX,OFFSET INSTALLED$
- MOV AH,09
- INT 21H ;DISPLAY MESSAGE.
-
- EXIT: MOV DX,OFFSET LOAD_CLOCK
- INT 27H ;EXIT - REMAIN RESIDENT.
-
- LOAD_CLOCK ENDP
-
- ;-------------------------------------------------------------------------
-
- INSTALLED$ DB 0AH,0DH,0AH,0DH,10 DUP(' ')
- DB 'Screen Clock has been installed.',0DH,0AH
- DB 10 DUP(' ')
- DB 'Press ALT-D to toggle on and off.',0DH,0AH,'$'
-
- ;-------------------------------------------------------------------------
-
- CODE_SEG ENDS
- END FIRST
-
- ;*******************************************************************************